#include "common.h"

// 计算文件的MD5值
int calculate_file_md5(const char *filename, char *md5_str) {
    FILE *file = fopen(filename, "rb");
    if (!file) {
        perror("fopen");
        return -1;
    }

    MD5_CTX md5_ctx;
    MD5_Init(&md5_ctx);

    char buffer[DEFAULT_BLOCK_SIZE];
    size_t bytes_read;

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
        MD5_Update(&md5_ctx, buffer, bytes_read);
    }

    unsigned char md5_hash[MD5_DIGEST_LENGTH];
    MD5_Final(md5_hash, &md5_ctx);

    fclose(file);

    // 将MD5哈希转换为字符串
    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(md5_str + 2 * i, "%02x", md5_hash[i]);
    }
    md5_str[32] = '\0';

    return 0;
}

// 计算内存块的MD5值
void calculate_block_md5(const void *data, size_t length, char *md5_str) {
    MD5_CTX md5_ctx;
    MD5_Init(&md5_ctx);
    MD5_Update(&md5_ctx, data, length);

    unsigned char md5_hash[MD5_DIGEST_LENGTH];
    MD5_Final(md5_hash, &md5_ctx);

    // 将MD5哈希转换为字符串
    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(md5_str + 2 * i, "%02x", md5_hash[i]);
    }
    md5_str[32] = '\0';
}

// 发送消息
ssize_t send_message(int sockfd, MessageType type, const void *data, size_t length) {
    MessageHeader header;
    header.type = type;
    header.length = length;

    // 发送消息头部
    ssize_t bytes_sent = send(sockfd, &header, sizeof(MessageHeader), 0);
    if (bytes_sent != sizeof(MessageHeader)) {
        perror("send header");
        return -1;
    }

    // 发送消息数据
    if (length > 0 && data != NULL) {
        bytes_sent = send(sockfd, data, length, 0);
        if (bytes_sent != (ssize_t)length) {
            perror("send data");
            return -1;
        }
    }

    return sizeof(MessageHeader) + length;
}

// 接收消息
ssize_t receive_message(int sockfd, MessageHeader *header, void **data) {
    // 接收消息头部
    ssize_t bytes_received = recv(sockfd, header, sizeof(MessageHeader), 0);
    if (bytes_received <= 0) {
        if (bytes_received < 0)
            perror("recv header");
        return bytes_received;
    }

    // 接收消息数据
    *data = NULL;
    if (header->length > 0) {
        *data = malloc(header->length);
        if (!*data) {
            perror("malloc");
            return -1;
        }

        bytes_received = recv(sockfd, *data, header->length, 0);
        if (bytes_received != (ssize_t)header->length) {
            perror("recv data");
            free(*data);
            *data = NULL;
            return -1;
        }
    }

    return sizeof(MessageHeader) + header->length;
}

// 错误处理函数
void error_exit(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

// 进度条显示函数
void print_progress(const char *filename, double progress, double speed, time_t elapsed) {
    const int bar_width = 50;
    int filled_width = (int)(bar_width * progress / 100);

    // 清除当前行
    printf("\033[2K\r");

    // 显示文件名和进度条
    printf("[%s] [", filename);
    for (int i = 0; i < bar_width; i++) {
        if (i < filled_width)
            printf("=");
        else if (i == filled_width)
            printf(">");
        else
            printf(" ");
    }

    // 显示百分比、速度和时间
    char time_str[32];
    strftime(time_str, sizeof(time_str), "%H:%M:%S", localtime(&elapsed));

    printf("] %.1f%% | Speed: %.2f KB/s | Time: %s",
           progress, speed, time_str);

    fflush(stdout);
}
